package com.tbit.uqbike.client.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tbit.common.constant.AccountSpikeConstant;
import com.tbit.uqbike.center.pojo.MachineStatus;
import com.tbit.uqbike.client.constant.*;
import com.tbit.uqbike.client.dao.core.BleBeaconDao;
import com.tbit.uqbike.client.dao.core.BleHelmetDao;
import com.tbit.uqbike.client.dao.core.MachineBorrowDao;
import com.tbit.uqbike.client.dao.core.MachineOccupyDao;
import com.tbit.uqbike.client.dao.log.*;
import com.tbit.uqbike.client.dao.ter.TerAttrExDao;
import com.tbit.uqbike.client.dao.ter.TerInfoDao;
import com.tbit.uqbike.client.pojo.*;
import com.tbit.uqbike.client.pojo.newEntity.*;
import com.tbit.uqbike.client.pojo.tlv.*;
import com.tbit.uqbike.client.service.*;
import com.tbit.uqbike.client.util.DateTimeUtil;
import com.tbit.uqbike.client.util.LogUtil;
import com.tbit.uqbike.client.util.ObjectUtil;
import com.tbit.uqbike.client.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

//@Service("queueListenter")
@Component
public class QueueListenter {

    private final static Logger log = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
    @Autowired
    private TerControlService terControlService;
    @Autowired
    private OrderLogDao orderLogDao;
    @Autowired
    private MachineService machineService;
    @Autowired
    private BleBeaconDao bleBeaconDao;
    @Autowired
    private RedisService redisService;
    @Autowired
    private OrderReturnDao orderReturnDao;
    @Autowired
    private MachineStatusService machineStatusService;
    @Autowired
    private ParkPointService parkPointService;
    @Autowired
    private MachineBorrowDao machineBorrowDao;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private BleHelmetDao bleHelmetDao;
    @Autowired
    private TerInfoDao terInfoDao;
    @Autowired
    private ForceFinishDao forceFinishDao;
    @Autowired
    private RuleRidePhotologDao ruleRidePhotologDao;
    @Autowired
    private ParkService parkService;
    @Autowired
    private RideLogService rideLogService;
    @Autowired
    private TerAttrExDao terAttrExDao;
    @Autowired
    private MachineOccupyDao machineOccupyDao;
    @Autowired
    private ThirdExceptionInfoDao thirdExceptionInfoDao;
    /**
     * 计算两个时间相差的秒数
     **/
    public static boolean inTime(Date startTime, Date endTime, Long time) {
        if (null == startTime || null == endTime) {
            return false;
        }
        long eTime = endTime.getTime();
        long sTime = startTime.getTime();
        long diff = (eTime - sTime) / 1000;

        return diff <= time;
    }

    /**
     * mac转道钉编号
     */

    public static String getTidUnit(String mac) {
        if (mac.startsWith("F")) {
            String tid = "";
            mac = new StringBuffer(mac).reverse().toString();

            char[] chars = mac.toCharArray();
            for (int i = 0; i < chars.length / 2; i++) {
                tid = tid + chars[2 * i + 1] + chars[2 * i];
            }

            tid = tid.replace("F", "0");
            return tid;

        } else {
            return mac.replace("F", "0");
        }
    }

    @RabbitListener(queues = {"${mq.exceptionQueue}"}, concurrency = "10")
    public void dealThirdException(Message msg){
        log.info("进入三方异常消费逻辑");
        try {
            String respMsg = new String(msg.getBody(), "UTF-8");
            ThirdExceptionInfo exceptionInfo = JSON.parseObject(respMsg, ThirdExceptionInfo.class);
            thirdExceptionInfoDao.add(exceptionInfo);
        }catch (Exception e){
            log.error("第三方系统异常日志消费出现异常",e);
        }
    }

    @RabbitListener(queues = {"${mq.queue}", "${mq.ddqueue}", "${mq.eventqueue}"}, concurrency = "5")
    public void onMessage(Message msg) {
        try {

            String respMsg = new String(msg.getBody(), "UTF-8");
            log.info(respMsg);
            /**判断消息类型*/

            JSONObject object = JSON.parseObject(respMsg);
            int msgId = object.getIntValue("msgId");
            switch (msgId) {
                case GatewayProtocol.MQ_MSG_ID_CONTROL_DOWN_RSP:
                    /*下发指令回复*/
                    break;
                case GatewayProtocol.MQ_MSG_ID_CONTROL_TER_RSP:

                    String serNO = object.getJSONObject("data").getString("serNO");

                    String controlRet = object.getJSONObject("data").getString("controlRet");
                    if (controlRet != null) {
                        /**指令耗时统计*/
                        OrderLog orderLogDB = orderLogDao.getByOrderNO(serNO);
                        if (orderLogDB != null && ("1".equals(orderLogDB.getOrderContent())
                                || "11".equals(orderLogDB.getOrderContent()))) {
                            Machine machine = machineService.getByMachineId(orderLogDB.getMachineId());
                            String endTime = DateTimeUtil.getNowTime();
                            Integer type = null;
                            if ("1".equals(orderLogDB.getOrderContent())) {
                                type = UseTimeConstant.OPEATE_RETURN;
                            } else if ("11".equals(orderLogDB.getOrderContent())) {
                                type = UseTimeConstant.OPEATE_BORROW;
                            }
                            ComsumTime comsumTime = new ComsumTime(machine.getAccountId(), orderLogDB.getOpId(),
                                    DateTimeUtil.StringToDateTime(orderLogDB.getOpTime())
                                    , DateTimeUtil.StringToDateTime(endTime), type, UseTimeConstant.USE_TIME_ORDER,
                                    (int) (System.currentTimeMillis() - DateTimeUtil
                                            .StringToDateTime(orderLogDB.getOpTime()).getTime()),
                                    orderLogDB.getMachineNo()
                                    , orderLogDB.getUserCode(), null, null, null, orderLogDB.getOrderSource(), null,
                                    null);
                            MqData mqData = new MqData();
                            mqData.setFeedback(RabbitMQData.aiQueue);
                            mqData.setMsgId(GatewayProtocol.MQ_MSG_ID_AROUND_TIME_PUSH);
                            mqData.setData(comsumTime);
                            SystemData.pushList.add(mqData);
                        }
                        String rspContent = "";
                        String exData = object.getJSONObject("data").getString("tlvs");
                        if (exData != null) {
                            JSONArray jsonArray = JSON.parseArray(exData);
                            for (int i = 0; i < jsonArray.size(); i++) {
                                /**跳过预还车指令*/
                                if (i == 0) {
                                    continue;
                                }
                                JSONObject jsonObject = jsonArray.getJSONObject(i);
                                rspContent = rspContent + jsonObject.toJSONString();
                            }
                        } else {
                            rspContent = object.toJSONString();
                        }
                        if (rspContent.length() >= 350) {
                            rspContent = rspContent.substring(0, 350);
                        }
                        /**记录终端返回结果*/
                        OrderLog orderLog = new OrderLog();
                        orderLog.setOrderSerNo(serNO);
                        orderLog.setRspDt(DateTimeUtil.getNowTime());
                        orderLog.setRspRet(Integer.valueOf(controlRet));

                        orderLog.setRspContent(rspContent);
                        orderLogDao.edit(orderLog);
                        /*终端回复*/
                        terControlService.respHandle(serNO, controlRet);
                    }

                    String paramRet = object.getJSONObject("data").getString("paramRet");
                    if (paramRet != null) {
                        OrderLog orderLogDB = orderLogDao.getByOrderNO(serNO);

                        if (orderLogDB != null) {
                            String picList = object.getJSONObject("data").getString("picList");
                            if (picList != null && !"".equals(picList)) {
                                OrderLog orderLog = new OrderLog();
                                orderLog.setOrderSerNo(serNO);
                                orderLog.setRspDt(DateTimeUtil.getNowTime());
                                orderLog.setRspRet(1);
                                orderLog.setRspContent(picList);
                                orderLogDao.edit(orderLog);

                                JSONArray jsonArray = JSON.parseArray(picList);
                                String ftpUrl = "";
                                for (int i = 0; i < jsonArray.size(); i++) {
                                    ftpUrl = ftpUrl + jsonArray.get(i).toString();
                                }

                                ForceFinish forceFinish = forceFinishDao.getByMachineId(orderLogDB.getMachineId());

                                if (forceFinish != null) {
                                    RuleRidePhotolog ruleRidePhotolog = new RuleRidePhotolog();
                                    ruleRidePhotolog.setPhotoId(forceFinish.getPhotoId());
                                    ruleRidePhotolog.setFtpUrl(ftpUrl);
                                    ruleRidePhotologDao.edit(ruleRidePhotolog);
                                }

                            } else if (ControlTypeConstant.CONTROL_AICAMERARET
                                    .equals(orderLogDB.getOrderContent())) {
                                /**硬解码*/
                                WebcamInfo webcamInfo = JSON.parseObject(paramRet, WebcamInfo.class);
                                OrderLog orderLog = new OrderLog();
                                orderLog.setOrderSerNo(serNO);
                                orderLog.setRspDt(DateTimeUtil.getNowTime());
                                orderLog.setRspRet(1);
                                orderLog.setRspContent(paramRet);
                                orderLogDao.edit(orderLog);

                                redisService.add(FunctionConstant.WEBCAM + orderLogDB.getMachineNo(),
                                        JSON.toJSONString(webcamInfo), 20);
                                /**记录日志*/

                                handelOrder(serNO, paramRet);
                            } else if (ControlTypeConstant.CONTROL_RFIDREADSTATUS
                                    .equals(orderLogDB.getOrderContent())) {
                                OrderLog orderLog = new OrderLog();
                                orderLog.setRspDt(DateTimeUtil.getNowTime());
                                orderLog.setOrderSerNo(serNO);
                                orderLog.setRspRet(1);
                                orderLog.setRspContent(paramRet);
                                orderLogDao.edit(orderLog);

                                redisService.add(FunctionConstant.RFID + orderLogDB.getMachineNo(), paramRet, 20);
                                /**兼容终端rfid指令返回6，触发重启rfid读卡器指令，开启开关配置，开关打开才触发*/

                                AccountConfigExt accountConfigExt = cacheService.getAccountConfigExtByKey(1,
                                        AccountConfigExtConstant.ACCOUNTCONFIG_POWER_CUT);

                                if (accountConfigExt != null && accountConfigExt.getParamValue().equals("1")) {
                                    JSONObject jsonObject = JSON.parseObject(paramRet);
                                    Integer ret = jsonObject.getInteger("ret");

                                    if (ret == GatewayProtocol.RSP_RESULT_RFID) {
                                        /**生成流水号*/

                                        String serNO1 = UUID.randomUUID().toString();
                                        terControlService.sendControl(serNO1, orderLogDB.getMachineNo(),
                                                ControlTypeConstant.CONTROL_TYPE_SET,

                                                ControlTypeConstant.CONTROL_TYPE_RFIDPOWER + "=0;",
                                                "0", null, true, -1, null, "");
                                        log.info("下发重启rfid读卡器指令" + serNO1);
                                    }
                                }

                                handelOrder(serNO, paramRet);
                            } else {
                                /**记录终端返回结果*/
                                OrderLog orderLog = new OrderLog();
                                orderLog.setOrderSerNo(serNO);
                                orderLog.setRspDt(DateTimeUtil.getNowTime());
                                orderLog.setRspRet(1);
                                orderLog.setRspContent(object.toJSONString());
                                orderLogDao.edit(orderLog);

                                String[] strings = paramRet.split(";");
                                for (String s : strings) {
                                    String tmp = s.substring(0, s.indexOf("="));
                                    tmp = tmp + ";";
                                    String value = s.substring(s.indexOf("=") + 1);
                                    if (ControlTypeConstant.CONTROL_TYPE_DEVICESTATUS.equals(tmp)) {
                                        //车辆状态
                                        redisService
                                                .add(FunctionConstant.CARSTATUS + orderLogDB.getMachineNo(), value, 20);
                                    } else if (ControlTypeConstant.CONTROL_TYPE_VEHHEADINGANGLE.equals(tmp)) {
                                        //垂直停车
                                        redisService
                                                .add(FunctionConstant.VERTICAL + orderLogDB.getMachineNo(), value, 11);
                                    } else if (ControlTypeConstant.CONTROL_TYPE_DEVICESTATUSEX.equals(tmp)) {
                                        if (!"fail".equalsIgnoreCase(value)) {
                                            String no = redisService
                                                    .get(RedisConstant.MACHINE_HELMET_EX + orderLogDB.getMachineNo());
                                            if (no != null) {
                                                /**缓存一天时间*/
                                                redisService
                                                        .add(RedisConstant.MACHINE_BORROW_EX + orderLogDB.getMachineNo(), value,
                                                                24 * 3600);
                                                redisService
                                                        .del(RedisConstant.MACHINE_HELMET_EX + orderLogDB.getMachineNo());
                                            } else {

                                                redisService
                                                        .add(FunctionConstant.CARSTATUSEX + orderLogDB.getMachineNo(), value,
                                                                20);
                                            }
                                        }
                                    }else if (ControlTypeConstant.CONTROL_TYPE_RGPS.equals(tmp)){
                                        redisService.add(RedisConstant.RETURN_RGPS + orderLogDB.getMachineNo(), value, 20);
                                    }
                                }
                                //handelOrder(serNO,paramRet);

                                log.info("流水号=" + serNO + ",结果=" + paramRet);
                            }
                        }

                    }
                    /**兼容控制指令附带tlvs返回*/

                    String tlvs = object.getJSONObject("data").getString("tlvs");
                    if (StringUtils.isNotEmpty(tlvs)) {
                        JSONArray jsonArray = object.getJSONObject("data").getJSONArray("tlvs");
                        OrderLog orderLogDB = orderLogDao.getByOrderNO(serNO);

                        if (orderLogDB == null) {
                            break;
                        }
                        TerInfo terInfo = terInfoDao.getByMachineNO(orderLogDB.getMachineNo());
                        boolean isXiaoAn = false;
                        if (terInfo != null && "XIAOAN".equalsIgnoreCase(terInfo.getFactoryCode())) {
                            isXiaoAn = true;
                        }
                        if ((terInfo == null || (!terInfo.getSoftVersion().contains("H-") || !terInfo
                                .getSoftVersion().contains("S-"))) && !isXiaoAn) {
                            break;
                        }

                        String soft = StringUtil.getHardCode(terInfo.getSoftVersion(), "S-");
                        /**tlvs逻辑处理*/

                        for (int i = 0; i < jsonArray.size(); i++) {
                            String tmp = jsonArray.getString(i);
                            Integer type = jsonArray.getJSONObject(i).getInteger("type");
                            switch (type) {
                                case WA206TLV.EX_TLV_TYPE_RETURN:

                                    break;
                                case WA206TLV.EX_TLV_TYPE_HELMET:
                                    /**智能头盔锁解析*/

                                    TlvHelmet tlvHelmet = JSON.parseObject(tmp, TlvHelmet.class);
                                    boolean gyisOk = false;
                                    boolean cxIsOk = false;
                                    /**锁舌关闭，未取出*/
                                    if ((isXiaoAn || StringUtil.getIndex(soft, 0)) && ObjectUtil.statusParse(2, tlvHelmet.sw)) {
                                        cxIsOk = true;
                                    }

                                    if ((isXiaoAn || StringUtil.getIndex(soft, 1)) && ObjectUtil.statusParse(1, tlvHelmet.sw)) {
                                        gyisOk = true;
                                    }
                                    if (gyisOk && !cxIsOk) {
                                        redisService.add(FunctionConstant.CARSTATUSEX + orderLogDB.getMachineNo(),
                                                String.valueOf(8), 20);
                                    }
                                    if (gyisOk && cxIsOk) {
                                        redisService.add(FunctionConstant.CARSTATUSEX + orderLogDB.getMachineNo(),
                                                String.valueOf(12), 20);
                                    }

                                    log.info("车辆状态isOk={},sw={}", gyisOk, tlvHelmet.sw);
                                    if (gyisOk && cxIsOk) {
                                        redisService.add(FunctionConstant.CARSTATUS + orderLogDB.getMachineNo(),
                                                String.valueOf(0), 20);
                                    } else {
                                        //将数据的第11位 置为0
                                        redisService
                                                .add(FunctionConstant.CARSTATUS + orderLogDB.getMachineNo(), "7820", 20);
                                    }

                                    break;
                                case WA206TLV.EX_TLV_TYPE_CAMERA_RET:
                                    /**摄像头*/
                                    TlvCameraRet tlvCameraRet = JSON.parseObject(tmp, TlvCameraRet.class);
                                    WebcamInfo webcamInfo = new WebcamInfo();
                                    int ret = tlvCameraRet.result;
                                    /**
                                     * 0x00 识别失败
                                     * 0x01 识别成功
                                     * 0x02 终端不支持该摄像头型号
                                     * 0x03 通信超时
                                     */
                                    if (ret == 2) {
                                        ret = GatewayProtocol.RSP_RESULT_STATUS8;
                                    } else if (ret == 3) {
                                        ret = GatewayProtocol.RSP_RESULT_STATUS9;
                                    }
                                    webcamInfo.setRet(ret);
                                    webcamInfo.setPicDir(tlvCameraRet.angle);
                                    webcamInfo.setSimilar(tlvCameraRet.similarity);
                                    redisService.add(FunctionConstant.WEBCAM + orderLogDB.getMachineNo(),
                                            JSON.toJSONString(webcamInfo), 20);
                                    break;
                                case WA206TLV.EX_TLV_TYPE_RFID_RET:
                                    /**RFID*/
                                    /**result 定义0x00 识别失败
                                     0x01 识别成功
                                     0x02 终端不支持该读卡器型号
                                     0x03 RFID读卡器通信超时*/
                                    TlvRfidInfo tlvRfidInfo = JSON.parseObject(tmp, TlvRfidInfo.class);
                                    getValue(RedisConstant.RFID_FAIL_KEY_PREFIX + orderLogDB.getMachineNo());
                                    JSONObject jsonObject = new JSONObject();
                                    int result = tlvRfidInfo.result;
                                    if (result == 2) {
                                        result = GatewayProtocol.RSP_RESULT_STATUS12;
                                    } else if (result == 3) {
                                        result = GatewayProtocol.RSP_RESULT_STATUS13;
                                    }
                                    jsonObject.put("ret", result);
                                    jsonObject.put("UID", tlvRfidInfo.UID);
                                    redisService.add(FunctionConstant.RFID + orderLogDB.getMachineNo(),
                                            JSON.toJSONString(jsonObject), 20);
                                    log.info("rfid=" + jsonObject);
                                    break;
                                case WA206TLV.EX_TLV_TYPE_BLE_RET:
                                    /**蓝牙道钉*/
                                    String bleInfoList = jsonArray.getJSONObject(i).getString("bleInfoList");
                                    List<BleNode> nodes = JSONArray.parseArray(bleInfoList, BleNode.class);
                                    if (!nodes.isEmpty()) {
                                        List<BleNode> ddnodes = new ArrayList<BleNode>();
                                        List<BleBeacon> bleBeacons = new ArrayList<>();
                                        for (BleNode bn : nodes) {
                                            String machineNO = getTidUnit(bn.getBleMAC());
                                            if (bn.getBleType() == 1) {
                                                bn.setBleTID(machineNO);
                                                ddnodes.add(bn);
                                                BleBeacon bleBeacon = new BleBeacon();
                                                bleBeacon.setMachineNO(machineNO);
                                                bleBeacon.setUpdateTime(new Date());
                                                bleBeacon.setMac(bn.getBleMAC());
                                                bleBeacons.add(bleBeacon);
                                            }
                                        }
                                        bleHandle(nodes, orderLogDB.getMachineNo(), bleBeacons);
                                    }
                                    break;
                                case WA206TLV.EX_TLV_TYPE_ANGLE_INFO:
                                    /**垂直停车*/
                                    TlvAngleInfo tlvAngleInfo = JSON.parseObject(tmp, TlvAngleInfo.class);
                                    getValue(RedisConstant.ANGLE_FAIL_KEY_PREFIX + orderLogDB.getMachineId());
                                    redisService.add(FunctionConstant.VERTICAL + orderLogDB.getMachineNo(),
                                            String.valueOf(tlvAngleInfo.deflectionAngle), 11);
                                    break;
                                case WA206TLV.EX_TLV_TYPE_NOMAL_HELMET:
                                    /**通用头盔锁*/
                                    TlvNormalHelmet tlvNormalHelmet = JSON.parseObject(tmp, TlvNormalHelmet.class);
                                    Integer sw = tlvNormalHelmet.sw;
                                    //boolean nomalIsOk = true;
                                    boolean gynomalisOk = false;
                                    boolean cxnomalIsOk = false;
                                    /**锁舌关闭，未取出*/
                                    if ((isXiaoAn || StringUtil.getIndex(soft, 0)) && ObjectUtil.statusParse(1, sw)) {
                                        cxnomalIsOk = true;
                                    }
                                    if ((isXiaoAn || StringUtil.getIndex(soft, 1)) && ObjectUtil.statusParse(2, sw)) {
                                        gynomalisOk = true;
                                    }
                                    if (gynomalisOk && !cxnomalIsOk) {
                                        redisService.add(FunctionConstant.CARSTATUSEX + orderLogDB.getMachineNo(),
                                                String.valueOf(8), 20);
                                    }
                                    if (gynomalisOk && cxnomalIsOk) {
                                        redisService.add(FunctionConstant.CARSTATUSEX + orderLogDB.getMachineNo(),
                                                String.valueOf(12), 20);
                                    }
                                    log.info("车辆状态nomalIsOk={},sw={}", gynomalisOk, sw);
                                    if (gynomalisOk && cxnomalIsOk) {
                                        redisService.add(FunctionConstant.CARSTATUS + orderLogDB.getMachineNo(),
                                                String.valueOf(0), 20);

                                    } else {
                                        //将数据的第11位 置为0
                                        redisService
                                                .add(FunctionConstant.CARSTATUS + orderLogDB.getMachineNo(), "7820", 20);
                                    }

                                    break;
                                case WA206TLV.EX_TLV_TYPE_BLE_HELMET:

                                    /**蓝牙头盔锁*/
                                    TlvBleHelmet tlvBleHelmet = JSON.parseObject(tmp, TlvBleHelmet.class);
                                    BleHelmet bleHelmet = new BleHelmet();
                                    bleHelmet.setSoc(tlvBleHelmet.soc);
                                    String mac = tlvBleHelmet.mac;

                                    mac = ObjectUtil.macCheck(mac);
                                    bleHelmet.setHelmetMac(mac);
                                    bleHelmet.setBatDt(new Date());
                                    bleHelmetDao.edit(bleHelmet);
                                    Integer bleState = 0;

                                    if (ObjectUtil.statusParse(1, tlvBleHelmet.sw)) {
                                        bleState = bleState + 1;
                                    }

                                    if (ObjectUtil.statusParse(2, tlvBleHelmet.sw)) {
                                        bleState = bleState + 2;
                                    }

                                    if (ObjectUtil.statusParse(0, tlvBleHelmet.helmetState)) {
                                        bleState = bleState + 4;
                                    }

                                    redisService.add(FunctionConstant.CARSTATUS + orderLogDB.getMachineNo(),
                                            String.valueOf(bleState), 20);

                                    break;
                                default:

                                    break;
                            }

                        }
                    }
                    break;
                case GatewayProtocol.MQ_MSG_ID_AROUND_BLES_PUSH:
                    /**解析蓝牙道钉数据*/

                    String arrayString = object.getJSONObject("data").getString("bleNodes");
                    List<BleNode> nodes = JSONArray.parseArray(arrayString, BleNode.class);
                    String mahcineNO = object.getJSONObject("data").getString("mno");
                    LogUtil.info(
                            "接收到中控融合定位包数据：mahcineNO[" + mahcineNO + "]json:[" + JSON.toJSONString(nodes) + "]");
                    List<BleBeacon> bleBeacons = new ArrayList<>();

                    if (nodes.size() > 0) {
                        /**----------------------------融合定位包开始----------------------------**/
                        /**融合定位包*/
                        Set mochineNoSet = new HashSet();

                        List<BleNode> newList = new ArrayList<BleNode>();
                        Date date = new Date();
                        /**道钉设备筛选*/

                        List<BleNode> ddnodes = new ArrayList<BleNode>();
                        for (BleNode bn : nodes) {
                            String machineNO = getTidUnit(bn.getBleMAC());
                            if (bn.getBleType() == 1) {
                                bn.setBleTID(machineNO);
                                ddnodes.add(bn);
                                BleBeacon bleBeacon = new BleBeacon();
                                bleBeacon.setMachineNO(machineNO);
                                bleBeacon.setUpdateTime(new Date());
                                bleBeacon.setMac(bn.getBleMAC());
                                bleBeacons.add(bleBeacon);
                            }

                            if (null != bn.getBleMAC()) {
                                bn.setMachineNO(bn.getBleMAC().replace("F", "").trim());
                            }
                            bn.setUpdateTime(date);
                            newList.add(bn);
                            mochineNoSet.add(bn.getMachineNO());
                        }
                        /**1.取出老的融合定位包数据**/

                        String rediskey = RedisConstant.CENTRALCONTROL_FUSELOCATION_DATA + mahcineNO;
                        List<BleNode> oldList = Optional.ofNullable(redisService.get(rediskey))

                                .map(o -> JSONObject.parseArray(o, BleNode.class))
                                .orElseGet(() -> null);

                        if (CollectionUtil.isNotEmpty(oldList)) {
                            for (BleNode o : oldList) {
                                /**20s内且机器号不重复的数据重新放回redis内**/

                                if (inTime(o.getUpdateTime(), date, 20l) && !mochineNoSet
                                        .contains(o.getMachineNO())) {
                                    newList.add(o);
                                }
                            }
                        }
                        /**2.将新的融合定位包数据存入redis**/

                        if (CollectionUtil.isNotEmpty(newList)) {

                            redisService.add(rediskey, JSON.toJSONString(newList), 20);
                        }
                        /**----------------------------融合定位包结束----------------------------**/

                        bleHandle(ddnodes, mahcineNO, bleBeacons);
                    } else {
                        /**传递无数据，清空缓存*/
                        redisService.del(RedisConstant.MACHINE_NO_BLEINFO + mahcineNO);
                    }
                    break;
                case GatewayProtocol.MQ_MSG_ID_EVENT_PUSH:
                    JSONObject jsonObject = object.getJSONObject("data");
                    Integer eventType= jsonObject.getInteger("eventType");
                    //单车单独处理静止临停事件
                    if(EventTypeConstant.EVENT_TYPE_0x08.equals(eventType)){
                        String mno= jsonObject.getString("mno");
                        Machine machine = machineService.getByMachineNO(mno);
                        if(machine==null){
                            return;
                        }
                        if(Objects.equals(machine.getMachineType(), MachineStateConstant.MACHINE_TYPE_BIKE)){
                            Park park = parkService.getByMachineId(machine.getMachineId());
                            if(park!=null){
                                return;
                            }
                            //删除运维占用记录
                            machineOccupyDao.delByMachineId(machine.getMachineId());
                            MachineBorrow machineBorrow = machineBorrowDao.getByMachineId(machine.getMachineId());
                            if(machineBorrow==null){
                                return;
                            }
                            long time =jsonObject.getLong("dt");
                            //添加临时停车日志
                           // RideLog rideLog = rideLogService.getByUserIdNotFinish(machineBorrow.getUserId());
                            park = new Park();
                            park.setAccountId(machine.getAccountId());
                            park.setUserId(machineBorrow.getUserId());
                            park.setMachineId(machine.getMachineId());
                            park.setStartTime(DateTimeUtil.DateTimeToString(new Date(time)));
                            park.setEndTime(DateTimeUtil.DateTimeToString(new Date(time)));
                            park.setRemark("中控静止自动临停锁车");
                            parkService.insert(park);

                            parkService.addLog(park);
                            //重置静止时间
                            TerAttrEx terAttrEx = new TerAttrEx();
                            terAttrEx.setDt(new Date(time));
                            terAttrEx.setMachineNO(machine.getMachineNO());
                            terAttrEx.setName("tLST");
                            terAttrExDao.edit(terAttrEx);
                            log.info("设备触发静止临停事件"+machine.getMachineNO());
                        }
                    }
                    break;
                case GatewayProtocol.MQ_MSG_ID_PHOTO_PUSH:
                    break;
                case GatewayProtocol.MQ_MSG_ID_EVENT_TLV_PUSH:
                    //事件推送
                    String data = object.getString("data");
                    if (data != null) {
                        terControlService.handelTlvs(data);
                    }

                    break;
                default:
                    log.warn("未知消息类型=" + msgId);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 道钉逻辑处理
     */
    public void bleHandle(List<BleNode> ddnodes, String machineNO, List<BleBeacon> bleBeacons) {
        if (ddnodes.size() > 0) {
            String orderNO = redisService.get(RedisConstant.RIDELOG_RETURN + machineNO);
            if (orderNO != null) {
                log.info(orderNO + "指令返回道钉信息=" + ddnodes);
            }
            List<BleInfo> list = new ArrayList<>();

            String tmp = redisService.get(RedisConstant.MACHINE_NO_BLEINFO + machineNO);
            if (tmp != null) {
                list = JSONObject.parseArray(tmp, BleInfo.class);
            }

            BleInfo bleInfo = new BleInfo();
            bleInfo.setNodes(ddnodes);
            bleInfo.setUpdateTime(System.currentTimeMillis());
            list.add(bleInfo);

            redisService.add(RedisConstant.MACHINE_NO_BLEINFO + machineNO, JSON.toJSONString(list), 20);
        }
        /**记录最后更新时间*/

        if (bleBeacons.size() > 0) {
            //禁行区蓝牙道钉判断
            accountSpikeCheck(bleBeacons, machineNO);
            /**更新最后修改时间*/

            for (BleBeacon bleBeacon : bleBeacons) {
                bleBeaconDao.editBatch(bleBeacon);
            }
        }
    }

    /**
     * 禁行区蓝牙道钉判断
     */
    private void accountSpikeCheck(List<BleBeacon> bleBeacons, String machineNO) {
        Machine machineInfo = cacheService.getMachineInfo(null, null, machineNO);
        if (machineInfo != null) {
            for (BleBeacon bleBeacon : bleBeacons) {
                Integer spikeType = SystemData.accountSpikeMap
                        .get(machineInfo.getAccountId() + "_" + bleBeacon.getMac());
                if (spikeType != null) {
                    //只对借出中车辆操作
                    MachineBorrow machineBorrow = machineBorrowDao.getByMachineId(machineInfo.getMachineId());
                    if (machineBorrow != null) {
                        //1分钟内不重复发送指令
                        String s = redisService.get(RedisConstant.ACCOUNT_SPIKE_PREFIX + machineNO);
                        if (!spikeType.toString().equals(s)) {
                            //是否是断电道钉
                            boolean flag = AccountSpikeConstant.POWER_OFF.equals(spikeType);
                            String paramName = flag ? ControlTypeConstant.CONTROL_TYPE_UNSTART
                                    : ControlTypeConstant.CONTROL_TYPE_UNLOCK;
                            String remark = flag ? "识别到断电道钉发送断电指令" : "识别到上电道钉发送上电指令";
                            log.info("禁行区蓝牙道钉判断,设备编号:{},{}", machineNO, remark);
                            terControlService.sendControl(UUID.randomUUID().toString(), machineNO,
                                    ControlTypeConstant.CONTROL_TYPE_CONTROL, paramName, "", machineInfo, false, 3,
                                    machineBorrow.getUserId(), remark);
                            redisService
                                    .add(RedisConstant.ACCOUNT_SPIKE_PREFIX + machineNO, spikeType.toString(), 60);
                            if (flag) {
                                redisService.add(RedisConstant.REDIS_MACHINE_FORBIDDEN_ID + machineNO, machineNO,
                                        24 * 3600);
                            } else {
                                redisService.del(RedisConstant.REDIS_MACHINE_FORBIDDEN_ID + machineNO);
                            }
                        } else {
                            log.info("禁行区蓝牙道钉判断,1分钟内不重复发送指令");
                        }
                    }
                    //识别到其中一个道钉就跳出循环
                    break;

                }
            }
        }


    }

    public void getValue(String key) {
        String tmp = redisService.get(key);
        if (!StringUtils.isEmpty(tmp)) {
            redisService.add(key, String.valueOf(Integer.valueOf(tmp) + 1), 60);
        }
    }

    /**
     * 处理指令结果
     */

    public void handelOrder(String orderNO, String paramRet) {
        OrderReturn orderReturnDB = orderReturnDao.getByOrderNO(orderNO);

        Machine machine = machineService.getByMachineNO(orderReturnDB.getMachineNO());
        if (orderReturnDB != null) {
            MachineStatus machineStatus = machineStatusService
                    .getByMachineNO(orderReturnDB.getMachineNO(), MapConstant.MAP_GOOGLE);
            Integer parkPointId = parkPointService.checkInParkPoint(orderReturnDB.getAccountId(),
                    new Point(machineStatus.getLon(), machineStatus.getLat()), machine.getMachineId(), null);
            JSONObject jsonObject = JSON.parseObject(paramRet);

            Integer ret = jsonObject.getInteger("ret");
            /**数据存入缓存推送至阿里云sls*/
            MachineBorrow machineBorrow = machineBorrowDao.getByMachineId(machine.getMachineId());

            if (machineBorrow != null) {
                Map<String, Object> rideMap = SystemData.ridelogMap.get(machineBorrow.getOrderNO());
                if (rideMap != null) {
                    rideMap.put("ret", ret);
                    rideMap.put("extraMsg", paramRet);
                }
            }
            //暂时处理保留180个字符
            if (StringUtils.isNotEmpty(paramRet) && paramRet.length() > 180) {
                log.info("{}指令结果返回过长，已截取，原指令结果={}", orderNO, paramRet);
                paramRet = paramRet.substring(0, 180);
            }
            OrderReturn orderReturn = new OrderReturn();
            orderReturn.setOrderNO(orderNO);
            orderReturn.setParkPointId(parkPointId);
            orderReturn.setResultMsg(paramRet);
            orderReturn.setRet(ret);
            orderReturn.setReturnTime(new Date());
            orderReturnDao.edit(orderReturn);
        }

    }

}
